package com.annotation;

/**
 * @功能：类的加载内存分析
 * @版本： V1
 * @版权： 信息技术有限公司（http://www.mychery.com/）
 * @作者： 磐石战队开发组  00355760
 * @日期： 2024/8/10 14:39
 */
public class demo06 {
    /**
     * 加载是指Java虚拟机查找字节流（查找.class文件），并且根据字节流创建java.lang.Class对象的过程。
     * 这个过程，将类的.class文件中的二进制数据读入内存，放在运行时区域的方法区内。然后在堆中创建java.lang.Class对象，用来封装类在方法区的数据结构。
     * 类加载阶段：
     1）Java虚拟机将.class文件读入内存，并为之创建一个Class对象。
     2）任何类被使用时系统都会为其创建一个且仅有一个Class对象。
     3）这个Class对象描述了这个类创建出来的对象的所有信息，比如有哪些构造方法，都有哪些成员方法，都有哪些成员变量等。
     * 链接
     * 链接包括验证、准备以及解析三个阶段。
     1）验证阶段。主要的目的是确保被加载的类（.class文件的字节流）满足Java虚拟机规范，不会造成安全错误。
     2）准备阶段。负责为类的静态成员分配内存，并设置默认初始值。
     3）解析阶段。将类的二进制数据中的符号引用替换为直接引用。
     * 初始化
     * 初始化，则是为标记为常量值的字段赋值的过程。换句话说，只对static修饰的变量或语句块进行初始化。
     * 如果初始化一个类的时候，其父类尚未初始化，则优先初始化其父类。
     * 如果同时包含多个静态变量和静态代码块，则按照自上而下的顺序依次执行。
     *
     * 具体说法如下：
     执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。
     (类构造器是构造类信息的，不是构造该类对象的构造器)。
     当初始化一个类的时候，如果发现其父类还没有进行初始化，则需要先触发其父类的初始化虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。
     虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。
     */
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.m);
    }

    /*
    1.加载到内存，会产生一个类对应的Class对象
    2.链接，结束后 m = 0;
    3.初始化
        <clinit>() {
            System.out.println("A类静态代码块初始化");
            m = 300;
            m = 100;
        }
     m = 100;
     */
}
class A {
    static {
        System.out.println("A类静态代码块初始化");
        m = 300;
    }
    static int m = 100;
    public A() {
        System.out.println("A类无参构造初始化");
    }
}